#pragma once

#include <msg_type.h>
#include <fstream>
#include <exception>
#include <iostream>
#include <filesystem>

struct FileTransfferStruct
{
	std::size_t transfferBytes_{ 0 };
	std::string sessionId_;
	std::string fileName_;
	std::fstream file_;
	std::size_t seq_{ 0 };

	FileTransfferStruct() = default;

	FileTransfferStruct(const std::string& sessionId):sessionId_(sessionId){}

	virtual ~FileTransfferStruct() {
		this->close();
	}

	size_t getSeq() {
		return seq_;
	}

	virtual bool isProcessFinish() { return false; };

	std::string getSessionId() {
		return sessionId_;
	}

	std::string getFileName() {
		return fileName_;
	}

	std::size_t getTransfferSize() {
		return transfferBytes_;
	}

	virtual bool openFile(const std::string& fileName) = 0;

	virtual std::size_t processBytes(char* buffer, size_t bytes) = 0;

	void close();
};

struct FileReadStruct :public FileTransfferStruct
{
	std::size_t fileSize_{ 0 };
	std::size_t bytesHasRead_{ 0 };

	FileReadStruct() = default;

	FileReadStruct(const std::string& sessionId):FileTransfferStruct(sessionId){}

	bool openFile(const std::string& fileName) override;

	std::size_t processBytes(char* buffer, size_t size) override;

	std::size_t readBytes(char* buffer, size_t size);

	bool isProcessFinish() override;

private:
	std::size_t getFileSize();
};

struct FileWriteStruct :public FileTransfferStruct
{
	FileWriteStruct() = default;

	FileWriteStruct(const std::string& sessionId) :FileTransfferStruct(sessionId) {}

	bool openFile(const std::string& fileName) override;

	std::size_t processBytes(char* buffer, size_t size) override;
	
	std::size_t writeBytes(char* buffer, size_t size);

};

struct FileAppendStruct :public FileTransfferStruct
{
	FileAppendStruct() = default;

	FileAppendStruct(const std::string& sessionId) :FileTransfferStruct(sessionId) {}

	bool openFile(const std::string& fileName) override;

	std::size_t processBytes(char* buffer, size_t size) override;

	std::size_t appendBytes(char* buffer, size_t size);

};